package com.cl.utility.util;

import com.cl.utility.constant.MockRandomValue;
import com.cl.utility.constant.PassInfo;
import net.datafaker.Faker;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.util.StringUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.Locale;
import java.util.UUID;

/**
 * @author liddhappy
 * @description 生成工具类
 * @createTime 2022/11/21 22:52
 */
public class GenerateUtils {

    /**
     *   Base64 编码是我们程序开发中经常使用到的编码方法，它用 64 个可打印字符来表示二进制数据。这 64 个字符是：小写字母 a-z、大写字母 A-Z、数字
     *   0-9、符号"+"、"/"（再加上作为垫字的"="，实际上是 65 个字符），其他所有符号都转换成这个字符集中的字符。Base64
     *   编码通常用作存储、传输一些二进制数据编码方法，所以说它本质上是一种将二进制数据转成文本数据的方案
     */

    /***
     * BASE64加密
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encode(key);
    }

    /***
     * BASE64解密
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryBASE64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }

    public static String BASE64Encoding(String input) {

        if (!StringUtils.isEmpty(input)) {
            try {
                byte[] bytes = input.getBytes(StandardCharsets.UTF_8.toString());
                return Base64.getEncoder().encodeToString(bytes);
            } catch (UnsupportedEncodingException e) {
                return null;
            }

        }
        return null;
    }

    public static String BASE64Decoding(String encoding) {
        if (!StringUtils.isEmpty(encoding)) {
            byte[] bytes = encoding.getBytes();
            return new String(Base64.getDecoder().decode(bytes), StandardCharsets.UTF_8);
        }
        return null;
    }

    /**
     * md5 生成Token Token
     *
     * @return
     */
    public static String makeToken() {
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        try {
            MessageDigest md = MessageDigest.getInstance("md5");
            byte md5[] = md.digest(token.getBytes());
            // base64编码--任意二进制编码明文字符
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(md5);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    public static String MD5(String str) {

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] array = md.digest(str.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
            }
            return sb.toString();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * checkPass:校验密码是否一致
     *
     * @param inputPass 用户传入的密码
     * @param salt      数据库保存的密码随机码
     * @param pass      数据库保存的密码MD5
     * @return
     */
    public static boolean checkPass(String inputPass, String salt, String pass) {
        String pwdMd5 = MD5(inputPass);
        return MD5(pwdMd5 + salt).equals(pass);
    }


    /**
     * buildPassword:用于用户注册时产生一个密码
     *
     * @param inputPass 输入的密码
     * @return PassInfo 返回一个密码对象，记得保存
     */
    public static PassInfo buildPassword(String inputPass) {

        //产生一个9位数的随机码
        String salt = RandomStringUtils.randomAlphabetic(9);
        //加密后的密码
        String encryptPassword = MD5(MD5(inputPass) + salt);
        //返回对象
        return new PassInfo(salt, encryptPassword);
    }

    private static final Faker ZH_FAKER = new Faker(new Locale("zh-CN"));

    private static final Faker EN_FAKER = new Faker();

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 获取随机值
     *
     * @param randomTypeEnum
     * @return
     */
    public static String getRandomValue(MockRandomValue randomTypeEnum) {
        String defaultValue = RandomStringUtils.randomAlphanumeric(2, 6);
        if (randomTypeEnum == null) {
            return defaultValue;
        }
        switch (randomTypeEnum) {
            case NAME:
                return ZH_FAKER.name().name();
            case CITY:
                return ZH_FAKER.address().city();
            case EMAIL:
                return EN_FAKER.internet().emailAddress();
            case URL:
                return EN_FAKER.internet().url();
            case IP:
                return ZH_FAKER.internet().ipV4Address();
            case INTEGER:
                return String.valueOf(ZH_FAKER.number().randomNumber());
            case DECIMAL:
                return String.valueOf(RandomUtils.nextFloat(0, 100000));
            case UNIVERSITY:
                return ZH_FAKER.university().name();
            case DATE:
                return EN_FAKER.date()
                        .between(Timestamp.valueOf("2022-01-01 00:00:00"), Timestamp.valueOf("2023-01-01 00:00:00"))
                        .toLocalDateTime().format(DATE_TIME_FORMATTER);
            case TIMESTAMP:
                return String.valueOf(EN_FAKER.date()
                        .between(Timestamp.valueOf("2022-01-01 00:00:00"), Timestamp.valueOf("2023-01-01 00:00:00"))
                        .getTime());
            case PHONE:
                return ZH_FAKER.phoneNumber().cellPhone();
            case UUID:
                return UUID.randomUUID().toString();
            default:
                return defaultValue;
        }
    }
}